"use strict";
/**
 * 解构对象
 */
// function createElement(options = {}){
//     let {width,height,backgroundColor} = options;
//     let div = document.createElement("div");
//     document.body.appendChild(div);
//     div.style.width = width + "px";
//     div.style.height = height + "px";
//     div.style.backgroundColor = backgroundColor;
// }
// let options = {
//     width:300,
//     height:400,
//     backgroundColor:"red"
// };
// createElement(options);




/**
 * 计算属性
 */
// let arr = [
//     {
//         title:"南方it",
//         name:"css"
//     },
//     {
//         title:"南方it",
//         name:"js"
//     },{
//         title:"南方it",
//         name:"html"
//     }
// ];

// let res = arr.reduce((obj,cur,index) => {
//     obj[`${cur.name}-${index + 1}`] = cur;
//     return obj;
// },{});
// console.log(JSON.stringify(res,null,2));
// console.log(res["css-1"]);




/**
 * 对象合并方法
 */
// let obj1 = {
//     name:"zwz",
//     age:17,
// };
// let obj2 = {
//     name:"zwz",
//     age:18,
//     index:8
// }
// let obj = Object.assign(obj1,obj2);
// console.log(obj);


/**
 * return 的问题
 */
// function number() {
//     // 这里需要注意一个问题，定时器里的return的值是返回给定时器的回调函数的，所以在number函数中他不生效
//     // 每一个return都是只在当前函数中生效，需要注意回调函数中的return使用
//     setTimeout(() => {
//         return 1000;
//     }, 1000);
//     return 900;
// }
// console.log(number());



/**
 * 利用递归实现对象深拷贝,
 * 如何实现深拷贝：目在于把对象里的值给拿出来，从而逃离对象传址
 * 有数组就在递归内使用instanceof判断
 */
// let data = {
//     name : "zwz",
//     user:{
//         name:"aaa",
//         age:17
//     },
//     arr:[]
// };

// function copy(object){
//     // 判断原对象内的值是数组还是对象
//     let res = object instanceof Array ? [] : {};
//     // 如果对象里包含user对象，就递归把user对象里的值重新赋值给一个res对象，
//     // 并return出来赋值给上一层的res对象，形成res[user] = res;
//     for (const [key,value] of Object.entries(object)) {
//         res[key] = typeof value == 'object' ? copy(value) : value;
//     }
//     return res;
// }

// let obj = copy(data);
// obj.user.name = "zcm";
// obj.user.age = 16;
// obj.arr.push("zwz");
// console.log(JSON.stringify(obj,null,2));
// console.log(JSON.stringify(data,null,2));




/**定义对象能否可写，遍历与删除*/
// let object = {
//     name:"Zwz",
//     age:17
// }
// console.log(JSON.stringify(Object.getOwnPropertyDescriptor(object,"name")));

// // 定义对象性质
// Object.defineProperty(object,"name",{
//     // 是否可写
//     writable:true,
//     // 是否可以遍历
//     enumerable:false,
//     // 是否可以配置，是否可以删除
//     configurable:false
// });
// object.name = "z";
// delete object.name;
// console.log(JSON.stringify(Object.getOwnPropertyDescriptor(object,"name")));




// // 访问器
// const user = {
//     data: {
//         name
//     },
//     // set访问器定义后的方法必须有一个值，当set关键字出现后，就会把定义的方法放到Object.defineProperty中，
//     // 再判断方法里是否有参数，没有就报错，这就是setter访问器的原理
//     set name(value) {
//         this.data.name = value;
//     },
//     get name() {
//         return this.data.name;
//     }
// };
// user.name = "zwz";
// console.log(user.name);




// 代理对象，也可以代理函数和数组
// const obj = {
//     name: "zwz",
//     age: 17
// };
// 
// let proxy = new Proxy(obj, {
//     // obj获取对象，property获取属性
//     get(obj, property) {
//         return obj[property];
//     },
//     // obj获取对象，property获取属性,value获取需要更改的值
//     set(obj, property, value) {
//         obj[property] = value;
//         return true;
//     }
// });
// proxy.age = 18;
// console.log(proxy.age);






/**
 * Vue双向绑定，原理是使用v-model绑定标签，并获取属性值以触发proxy的set访问器
 */
// function view() {
//     const proxy = new Proxy({}, {
//         get(obj, property) {},
//         set(obj, property, value) {
//             // 使用querySelectorAll获取到拥有v-model的标签，并且赋值
//             document.querySelectorAll(`[v-model="${property}"]`).forEach(item => {
//                 item.value = value;
//             });
//             document.querySelectorAll(`[v-bind="${property}"]`).forEach(item => {
//                 item.innerHTML = value;
//             });
//             return true;
//         }
//     });

//     this.init = function () {
//         const model = document.querySelectorAll("[v-model]");
//         model.forEach(item => {
//             item.addEventListener("keyup", function () {
//                 // 使用getAttribute获取属性值，并触发proxy的set访问器进行赋值
//                 proxy[this.getAttribute("v-model")] = this.value;
//             });
//         });
//     }
// }
// new view().init();



/**
 * 代理工厂，注意，遍历proxy时会调用get方法，所以要配置好get方法，不然会报错
 */
// function ProxyFactory(target) {
//     return new Proxy(target, {
//         get(target, key) {
//             return target[key];
//         },
//         set() {}
//     });
// }

// const proxy = ProxyFactory(document.querySelectorAll("[test]"));
// proxy.forEach(item => {
//     console.log(item);
// });




/**
 * 转换对象或数组为JSON格式和把JSON转换成js
 */

// let obj = {
//     name: "zwz",
//     age: 17,
//     sex: "man"
// }
// // 第一参数为对象，第二参数为保留的属性，第三为代码缩进的行数
// let json = JSON.stringify(obj, ["name", "age"], 2);
// console.log(json);

// // 将JSON转换成js格式
// // 第一参数为需要转换的JSON，第二参数为操作函数
// let jsonParse = JSON.parse(json, (key, value) => {
//     console.log(key, value);
// });